package com.power.sifa.approve.service.impl;

import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.domain.YesNo;
import com.plf.common.file.service.impl.MinioFileService;
import com.plf.common.utils.FileUtil;
import com.plf.common.utils.SpringHolder;
import com.plf.common.utils.StringUtil;
import com.plf.core.base.model.Ha_attachment;
import com.plf.core.base.service.Ha_attachmentService;
import com.plf.core.common.service.BaseServiceImpl;
import com.power.sifa.approve.dao.Apl_matter_attachDao;
import com.power.sifa.approve.model.Apl_main;
import com.power.sifa.approve.model.Apl_matter_attach;
import com.power.sifa.approve.model.Material_attach;
import com.power.sifa.approve.model.enumeration.Tp_mattype;
import com.power.sifa.approve.model.pageInfo.Apl_matter_attachPageInfo;
import com.power.sifa.approve.service.*;
import com.power.sifa.std.service.Std_matter_attachService;
import com.power.sifa.std.service.Std_matter_attach_secondService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 *  申请材料业务层实现
 */
@Slf4j
@Service
public class Apl_matter_attachServiceImpl extends BaseServiceImpl implements Apl_matter_attachService {

    @Resource
    private Apl_matter_attachDao dao;
    @Resource
    private Std_matter_attachService std_matter_attachService;
    @Resource
    private Apl_attachmentService apl_attachmentService;
    @Resource
    private Std_matter_attach_secondService std_matter_attach_secondService;
    /**
     * 申请材料附件生成路径
     */
    @Value("${power.file-path:#{null}}")
    private String filePath;

    @Autowired
    private Ha_attachmentService ha_attachmentService;
    @Autowired
    private MinioFileService minioFileService;

    @Override
    public Apl_matter_attach getById(Serializable id) {
        return dao.findById(id).orElse(null);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdate(Apl_matter_attach apl_matter_attach) {
    	// save 如果数据库不存在这条数据，就会执行保存（即将这条数据插入到数据库）；如果数据库存在这条数据，就会根据主键去更新这条数据
        if (apl_matter_attach.getPrimaryKey() != null) {
        	 Apl_matter_attach apl_matter_attachfDb = dao.findById(apl_matter_attach.getPrimaryKey()).orElse(null);
             if(apl_matter_attachfDb != null) {
                BeanUtils.copyProperties(apl_matter_attach, apl_matter_attachfDb);
                dao.save(apl_matter_attachfDb);
                return;
             }
        }
        dao.save(apl_matter_attach);
    }

    @Override
    public void removeById(Serializable id) {
        dao.deleteById(id);
    }

    @Override
    public Page<Apl_matter_attach> findAll(Apl_matter_attachPageInfo pageInfo) {
        //排序等定义
        Sort sort;
        if("asc".equals(pageInfo.getOrder())) {
            sort = Sort.by(Sort.Direction.ASC, pageInfo.getSort());
        }else {
            sort = Sort.by(Sort.Direction.DESC, pageInfo.getSort());
        }
        //分页的定义
        Pageable pageable = PageRequest.of(pageInfo.getPageNumber()<=1 ? 0 : pageInfo.getPageNumber()-1, pageInfo.getPageSize(), sort);
        //查询条件
        Specification spec = this.createSpecification(pageInfo);
        return dao.findAll(spec, pageable);
    }

    @Transactional(rollbackFor = Exception.class)
    public void removeByIds(List<Integer> ids) {
        dao.removeByIds(ids);
    }

    @Override
	public List<Apl_matter_attach> findAll() {
		return dao.findAll();
	}

	@Override
	public void saveAll(List<Apl_matter_attach> list) {
		dao.saveAll(list);
	}

    @Override
    public List<Apl_matter_attach> init(String applyid, String matid) {
        List<Apl_matter_attach> apl_matter_attachs = dao.queryListByApplyid(applyid);
        if(CollectionUtils.isEmpty(apl_matter_attachs)) {
            // 初次进入申请材料，先通过事项id获取申请材料配置列表
            apl_matter_attachs = this.generate(applyid, matid);
            // 将申请材料配置列表保存至申请材料中
            this.saveAll(apl_matter_attachs);
        }
        return apl_matter_attachs;
    }

    /**
     * 生成申请材料
     * @param applyid
     * @param matid
     * @return
     */
    private List<Apl_matter_attach> generate(String applyid, String matid) {
        List<Apl_matter_attach> apl_matter_attachs = new ArrayList<>();
        List<Map<String, Object>> list = std_matter_attachService.queryListByMatid(matid);
        if(CollectionUtils.isEmpty(list)) {
            return apl_matter_attachs;
        }
        Apl_matter_attach apl_matter_attach;
        for(Map map : list) {
            apl_matter_attach = new Apl_matter_attach();
            apl_matter_attach.setId(NanoIdUtils.randomNanoId());
            apl_matter_attach.setApplyid(applyid);
            apl_matter_attach.setSortnum(Integer.valueOf(String.valueOf(map.get("sortnum"))));
            apl_matter_attach.setName((String) map.get("name"));
            apl_matter_attach.setRequire(Integer.valueOf(String.valueOf(map.get("require"))));
            apl_matter_attach.setMaxnum(Integer.valueOf(String.valueOf(map.get("maxnum"))));
            apl_matter_attach.setDescribe((String) map.get("describe"));
            apl_matter_attach.setFiledown(Integer.valueOf(String.valueOf(map.get("filedown"))));
            apl_matter_attach.setFilemake((String) map.get("filemake"));
            apl_matter_attach.setStdattachid((String) map.get("attachid"));
            if(!StringUtil.isEmpty((String) map.get("mattertpl"))) {
                apl_matter_attach.setTplfile((String) map.get("mattertpl"));
            } else if(!StringUtil.isEmpty((String) map.get("attachtpl"))) {
                apl_matter_attach.setTplfile((String) map.get("attachtpl"));
            } else {
                apl_matter_attach.setTplfile(null);
            }
            if(map.get("maxfilesize") != null) {
                apl_matter_attach.setMaxfilesize(Integer.valueOf(String.valueOf(map.get("maxfilesize"))));
            }
            apl_matter_attach.setIsmanual(YesNo.NO);
            apl_matter_attach.setDeleted(0);
            apl_matter_attachs.add(apl_matter_attach);
        }
        return apl_matter_attachs;
    }

    @Override
    public List<Apl_matter_attach> queryListAndFileByApplyid(String applyid) {
        List<Apl_matter_attach> apl_matter_attachs = dao.queryListByApplyid(applyid);
        if(CollectionUtils.isEmpty(apl_matter_attachs)) {
            return null;
        }
        Map attachmentMap = apl_attachmentService.queryList(applyid);
        if(attachmentMap == null) {
            return apl_matter_attachs;
        }
        for(Apl_matter_attach apl_matter_attach : apl_matter_attachs) {
            List<Map> fileList = (List<Map>) attachmentMap.get(apl_matter_attach.getId());
            if(!CollectionUtils.isEmpty(fileList)) {
                fileList = fileList.stream().sorted(Comparator.comparing(map -> (String) map.get("createtime"))).collect(Collectors.toList());
            }
            apl_matter_attach.setFileList(fileList);
        }
        return apl_matter_attachs;
    }

    @Override
    public void downloadMaterialAll(String applyid, HttpServletResponse response) throws Exception {
        Apl_mainService apl_mainService = SpringHolder.getBean(Apl_mainServiceImpl.class);
        Apl_main apl_main = apl_mainService.getById(applyid);
        // 根据申请编号创建根文件夹
        File rootFile = new File(this.filePath+"/"+apl_main.getApplycode());
        rootFile.mkdirs();

        // 获取其他材料附件
        List<Map> apl_attachments = apl_attachmentService.getListByApplyid(applyid);
        if(!CollectionUtils.isEmpty(apl_attachments)) {
            // 材料附件列表
            List<Map> materialMapList = new ArrayList<>();
            Map materialMap;
            // 附件id
            List<String> attachIds = new ArrayList<>();

            for(Map apl_attachment : apl_attachments) {
                attachIds.add((String) apl_attachment.get("attachmentid"));
                materialMap = new HashMap();
                materialMap.put("material_name", apl_attachment.get("material_name"));
                materialMap.put("attach_id", apl_attachment.get("attachmentid"));
                materialMapList.add(materialMap);
            }

            List<Material_attach> material_attaches = this.getMaterialAttachList(materialMapList, attachIds);
            if(!CollectionUtils.isEmpty(material_attaches)) {
                for(Material_attach material_attach : material_attaches) {
                    // 在本地创建材料文件
                    File file = new File(rootFile.getAbsolutePath()+"/"+material_attach.getMaterial_name());
                    if(!file.exists()) {
                        file.mkdirs();
                    }
                    try (FileOutputStream fos = new FileOutputStream(new File(file.getAbsolutePath()+"/"+material_attach.getFile_name()))) {
                        fos.write(material_attach.getFile_byte());
                    }catch (Exception e) {
                        log.error("下载材料文件失败:{}", e.getMessage());
                    }
                }
            }
        }

        // 压缩文件为zip格式
        FileUtil.toZip(rootFile.getAbsolutePath(), true);
        // 下载材料文件
        FileUtil.download(response, rootFile.getAbsolutePath()+".zip", apl_main.getApplycode()+".zip");
        // 删除材料文件
        FileUtil.delDir(rootFile);
        FileUtil.delDir(new File(rootFile.getAbsolutePath()+".zip"));
    }

    @Override
    public List<Material_attach> getMaterialAttachList(List<Map> materialMapList, List<String> attachIds) {
        // 通过附件id查询所有附件对象
        Map<String, Ha_attachment> attachMap = ha_attachmentService.getHa_attachmentMapByIds(attachIds);
        if(CollectionUtils.isEmpty(attachMap)) {
            return null;
        }
        List<Material_attach> list = new ArrayList<>();
        Material_attach material_attach;
        Ha_attachment ha_attachment;
        try {
            InputStream is;
            for(Map map : materialMapList) {
                material_attach = new Material_attach();
                material_attach.setMaterial_name((String) map.get("material_name"));
                if(map.get("stdattachid") != null) {
                    material_attach.setStdattachid(map.get("stdattachid").toString());
                }

                ha_attachment = attachMap.get(map.get("attach_id"));
                if(ha_attachment == null) {
                    continue;
                }
                material_attach.setFile_id(ha_attachment.getId());
                material_attach.setFile_name(ha_attachment.getFilename());
                material_attach.setFile_type(ha_attachment.getFiletype());
                material_attach.setFile_size(ha_attachment.getFilesize());
                is = minioFileService.getStream(ha_attachment.getBucket(), ha_attachment.getPath());
                material_attach.setFile_byte(IOUtils.toByteArray(is));
                material_attach.setFile_byteStr(new String(material_attach.getFile_byte(), "ISO-8859-1"));
                is.close();
                list.add(material_attach);
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return list;
    }

    @Override
    public ResponseDTO check(String applyid) {
        List<Apl_matter_attach> apl_matter_attachs = dao.queryListByApplyid(applyid);
        if(CollectionUtils.isEmpty(apl_matter_attachs)) {
            return ResponseDTO.wrap(500, "未查询到材料列表");
        }
        List<String> matter_attachids =  apl_attachmentService.getMatterAttachid(applyid);
        if(CollectionUtils.isEmpty(matter_attachids)) {
            matter_attachids = new ArrayList<>();
        }
        for(Apl_matter_attach apl_matter_attach : apl_matter_attachs) {
            if (apl_matter_attach.getRequire() == YesNo.YES && !matter_attachids.contains(apl_matter_attach.getId())) {
                return ResponseDTO.wrap(500, "请上传材料：" + apl_matter_attach.getName());
            }
        }
        return ResponseDTO.succ();
    }

    @Override
    public void refresh(String applyid, String matid, List<String> types) {
        Map<String, Integer> attachSecondMap = std_matter_attach_secondService.queryMap(matid, types);
        if(attachSecondMap == null) {
            return;
        }
        List<Apl_matter_attach> apl_matter_attachList = dao.queryAllListByApplyid(applyid);
        if(CollectionUtils.isEmpty(apl_matter_attachList)) {
            apl_matter_attachList = this.generate(applyid, matid);
        }
        for(Apl_matter_attach apl_matter_attach : apl_matter_attachList) {
            if(apl_matter_attach.getIsmanual() == YesNo.YES) {
                continue;
            }
            if(attachSecondMap.containsKey(apl_matter_attach.getStdattachid())) {
                apl_matter_attach.setDeleted(0);
                apl_matter_attach.setRequire(attachSecondMap.get(apl_matter_attach.getStdattachid()));
            }else {
                apl_matter_attach.setDeleted(1);
            }
        }
        this.saveAll(apl_matter_attachList);
    }

    @Override
    public List<Apl_matter_attach> queryThirdPersonMaterial(String applyid) {
        List<Apl_matter_attach> apl_matter_attachs = this.dao.getListByApplyid(applyid, Tp_mattype.THIOTHER);
        if(CollectionUtils.isEmpty(apl_matter_attachs)) {
            return null;
        }
        Map attachmentMap = apl_attachmentService.queryList(applyid);
        if(attachmentMap == null) {
            return apl_matter_attachs;
        }
        for(Apl_matter_attach apl_matter_attach : apl_matter_attachs) {
            List<Map> fileList = (List<Map>) attachmentMap.get(apl_matter_attach.getId());
            if(!CollectionUtils.isEmpty(fileList)) {
                fileList = fileList.stream().sorted(Comparator.comparing(map -> (String) map.get("createtime"))).collect(Collectors.toList());
            }
            apl_matter_attach.setFileList(fileList);
        }
        return apl_matter_attachs;
    }
}
